何謂 Scope 呢? 簡單來講就是
規範哪些變數在哪些程式碼中可以取用的規則
Scope 主要分成兩種類型:
JavaScript 與大多數的語言相同是採用 Lexiacal Scope。以下讓我們來介紹 Lexical Scope ( 語彙範疇 )
代表著區塊間的包裹關係,被包裹在內層的區塊可以保護自己的變數不被外層取用,相反的外層區塊的變數還是可以被內層區塊使用
這麼講可能很抽象,那就讓我們來看看範例:
var outer = 'From Outer';
function myFunction() {
  var inner = 'From Inner';
  console.log(outer);				// "From Outer"
  console.log(inner);				// "From Inner"
}
console.log(outer);					// "From Outer"
console.log(inner);					// Uncaught ReferenceError: inner is not defined
myFunction 包裹出一個 {} 區塊,並在內部新宣告了一個變數 inner。inner可以在 myFunction 區塊裡的被取用,然而當 myFunction 區塊的外面試圖取用 inner 時,就會發生 Uncaught ReferenceError: innerVar is not defined 的錯誤。
再回過頭來看 outer。outer 是外層區塊宣告的變數,因此不論是 myFunction 的內層區塊還是 outer 自己所在的外層區塊,都是可以取用到 outer 的。
讓我們將這段程式碼換成更容易理解的圖:

圖中的橘色區塊中宣告的變數無法被藍色區塊取用
再讓我們複習一次:被包裹在內層的區塊可以保護自己的變數不被外層取用,相反的外層區塊的變數還是可以被內層區塊使用。
還記得 JavaScript 傳值篇所講的,當參數傳遞進 Function 的時候,會先將內容指派給一個新的變數:
var myString = 'hello world';
function setAsLiteralObj(target) {
	target = {};
}
setAsLiteralObj(myString);
console.log(myString);					// 'hello world'
console.log(target);					// Uncaught ReferenceError: target is not defined
執行 setAsLiteralobj(myString); 時, myString 會將記憶體位置指派給 function 中的新參數 target,我們可以把他理解成:
var target = myString;
也就是 target 是在執行 setAsLiteralObj 時才會新建的參數,這個新建的變數也是屬於 setAsLiteralObj  函式區塊的,所以試圖在外層印出 target 時,才會得到 Uncaught ReferenceError: target is not defined 的錯誤訊息。
為了改正我們的觀念,應該把泡泡圖改成這樣:

當我們有多個區塊時,那就會出現巢狀 Scope:
var outer = 'outer';
function myFunction() {
  var middle = 'middle';
  function myInnerFunction() {
    var inner = 'inner';
  }
  myInnerFunction();
}
myFunction();
規則也是同樣的:外層 Scope 無法取用內層變數,但內層 Scope 可以取用外層變數

從上面的說明,我們不難發現,Lexical Scope 是在程式編寫時就決定好了,因為區塊的擺放位置是我們在寫程式的時候決定,而不是 JavaScript 的編譯器為我們產生的。
再更進一步思考就是,在編寫時期我們就可以決定哪個變數可以被何處取用,這是要建立易於維護的程式碼時必須要有的基本認知。
本篇主要介紹 Lexical Scope
Scope 主要分成兩種類型:
而 JavaScript 是採用 Lexical Scope ( 語彙範疇 )
Lexical Scope 代表著區塊間的包裹關係,他的規則是:
Lexical Scope 是在程式編寫時就決定好了,因為區塊的擺放位置是我們在寫程式的時候就決定好了,這代表著在編寫時期我們就可以決定哪個變數可以被何處取用,這是要建立易於維護的程式碼時必須要有的重要觀念。
You Don't Know JS: Scope & Closure